from datetime import datetime
import threading
import time
from multiprocessing import Queue
from queue import Empty
import psutil


class Monitor:
    def __init__(self, log_queue=None, callback=None):
        self.status = "Stopped"
        self.log_queue = log_queue
        self.callback = callback
        self.running = False
        self.monitor_thread = None
        self.stats_thread = None

    def start(self):
        """启动监控"""
        self.status = "Running"
        self.running = True

        if self.log_queue and self.callback:
            self.monitor_thread = threading.Thread(target=self._monitor_logs)
            self.stats_thread = threading.Thread(target=self._monitor_stats)
            self.monitor_thread.daemon = True
            self.stats_thread.daemon = True
            self.monitor_thread.start()
            self.stats_thread.start()

        if self.callback:
            self.callback("监控服务已启动")

    def stop(self):
        """停止监控"""
        self.status = "Stopped"
        self.running = False

        if self.monitor_thread:
            self.monitor_thread.join()
        if self.stats_thread:
            self.stats_thread.join()

        if self.callback:
            self.callback("监控服务已停止")

    def get_status(self):
        return self.status

    def check_port(self, port):
        """检查指定端口是否开放"""
        import socket
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(1)
        result = sock.connect_ex(('localhost', port))
        sock.close()
        return result == 0

    def _monitor_logs(self):
        """监控Web服务器日志"""
        if self.callback:
            self.callback("日志监控服务已启动...")

        while self.running:
            try:
                # 非阻塞方式获取日志
                try:
                    log_entry = self.log_queue.get(timeout=0.1)
                    if self.callback:
                        self.callback("收到日志条目")
                except Empty:
                    continue

                if not isinstance(log_entry, dict):
                    if self.callback:
                        self.callback(f"收到非字典格式的日志: {log_entry}")
                    continue

                if log_entry.get('type') and log_entry.get('data'):
                    data = log_entry['data']
                    if log_entry['type'] == 'request':
                        log_message = (
                            f"[{data['timestamp']}] 新请求:\n"
                            f"  方法: {data['method']}\n"
                            f"  路径: {data['path']}\n"
                            f"  来源: {data['remote_addr']}\n"
                            f"  客户端: {data['user_agent']}"
                        )
                        if data.get('data'):
                            log_message += f"\n  数据: {data['data']}"
                    elif log_entry['type'] == 'log':
                        log_message = (
                            f"[{data['timestamp']}] {data['message']}"
                        )
                    else:
                        if self.callback:
                            self.callback(f"未知的日志类型: {log_entry['type']}")
                        continue

                    if self.callback:
                        self.callback(log_message)
                else:
                    if self.callback:
                        self.callback(f"日志条目格式不正确: {log_entry}")
            except Exception as e:
                if self.callback:
                    self.callback(f"[错误] 日志监控异常: {str(e)}")
                time.sleep(1)  # 发生错误时等待一秒

    def _monitor_stats(self):
        """监控服务器状态"""
        while self.running:
            try:
                # 获取进程统计信息
                process = psutil.Process()
                cpu_percent = process.cpu_percent(interval=1)
                memory_info = process.memory_info()

                stats_message = (
                    f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 服务器状态:\n"
                    f"  CPU使用率: {cpu_percent}%\n"
                    f"  内存使用: {memory_info.rss / 1024 / 1024:.2f} MB\n"
                    f"  线程数: {process.num_threads()}"
                )
                self.callback(stats_message)

                # 每30秒更新一次状态
                for _ in range(30):
                    if not self.running:
                        break
                    time.sleep(1)

            except Exception as e:
                self.callback(f"[错误] 状态监控异常: {str(e)}")
                time.sleep(30)  # 发生错误时等待30秒再重试
